package com.travelsky.server.chat_socket;

import java.io.IOException;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContextBuilder;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;

import com.travelsky.server.jdbc.Base64Util;
import com.travelsky.server.vo.coverage.Coverage;
import com.travelsky.server.vo.coverage.Measures;
import com.travelsky.server.vo.git.Git;
import com.travelsky.server.vo.git.Pipelines;
import com.travelsky.server.vo.sonar.Facets;
import com.travelsky.server.vo.sonar.Sonar;
import com.travelsky.server.vo.sonar.Values;

/**
 * HttpClient线程类，用于到Git和Sonar网上获取数据
 ******************************************
 * @author HuangFeng  [2017年7月5日 下午12:57:39]
 * @version 1.0
 ******************************************
 */
public class HttpClientThread extends Thread {

	private String gitLabUrl;
	private String sonarUrl;
	private String sonarCoverageUrl;
	private String git_username;
	private String git_password;
	private Map<String, CloseableHttpClient> httpclientMap = new HashMap<String, CloseableHttpClient>();
	private ServerThread serverThread; // 服务器端线程
	private Git git; //Git 的状态
	private Sonar sonar; //Sonar 的状态
	private Coverage coverage;//分支覆盖率信息
	private boolean flag_exit = false;

	/**构造方法
	 ******************************************
	 * @author HuangFeng [2017年7月5日 下午1:55:34]
	 * @version 1.0
	 ******************************************
	 */
	public HttpClientThread() {
	}
	
	/**
	 * 构造方法
	 ******************************************
	 * @author HuangFeng [2017年7月5日 下午12:58:57]
	 * @version 1.0
	 ******************************************
	 * @param serverThread 服务器线程类对象
	 */
	public HttpClientThread(ServerThread serverThread) {
		this.serverThread = serverThread;
		this.gitLabUrl = serverThread.config.getGitLabJsonUrl();
		this.sonarUrl = serverThread.config.getSonarJsonUrl();
		this.git_username = serverThread.config.getGitUserName();
		this.git_password = Base64Util.base64decode(serverThread.config.getGitPassword());
		this.sonarCoverageUrl = serverThread.config.getSonarCoverageUrl();
		//登录GitLab
		loginGitLab();
		//构建sonar
		build("sonar",sonarUrl);
		//构建sonarCoverage
		build("sonarCoverage",sonarCoverageUrl);
	}

	@Override
	public void run() {
		ObjectMapper om = new ObjectMapper();
		//忽略没有的字段 not marked as ignorable
		om.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		Integer count = 101;
		String gitJson = "";
		String sonarJson = "";
		String sonarCoverage = "";
		while (flag_exit) {
			try {
				sleep(6000);//睡眠6秒再获取数据
				count++;
				//获取Git上JSON格式的数据
				gitJson = doGet("gitLab",gitLabUrl, null);
				if(!gitJson.isEmpty()){
					git = om.readValue(gitJson, Git.class);
				}
				//sonar十分钟获取一次
				if(count>100){
					count = 0;
					//获取Sonar上JSON格式的数据
					sonarJson = doGet("sonar",sonarUrl, null);
					//获取Sonar上分支覆盖率等JSON格式的数据
					sonarCoverage = doGet("sonarCoverage",sonarCoverageUrl, null);
					if(!sonarJson.isEmpty()){
						sonar = om.readValue(sonarJson, Sonar.class);
					}
					if(!sonarJson.isEmpty()){
						coverage = om.readValue(sonarCoverage, Coverage.class);
					}
				}
			} catch (Exception e1) {
				serverThread.server.sendEmail(e1.getMessage()+"\ngitJson: "+gitJson+"\nsonarJson: "+sonarJson);
				continue;
			}
			int i = 0;
			StringBuffer msg = new StringBuffer();
			for (i = 0; i < git.pipelines.size(); i++) {
				Pipelines pipelines = git.pipelines.get(i);
				String id = pipelines.id;
				String name = pipelines.user.name;
				String status = pipelines.details.status.group;
				msg.append("#" + id + ":" + name + "-" + status + "@Git");
				if (status.equals("success")) {
					break;
				}
			}
			msg.append("@Sonar");
			if(sonar != null){
				List<Facets> facets = sonar.getFacets();
				List<Values> values = new ArrayList<Values>();
				for (Facets facet : facets) {
					if(facet.getProperty().equals("severities")){
						values = facet.getValues();
						break;
					}
				}
				for(i=values.size()-1;i>=0;i--){
					msg.append(values.get(i).getVal()+":"+values.get(i).getCount()+"@Sonar");
				}
			}
			msg.append("@Coverage ");
			if(coverage != null){
				List<Measures> measures = coverage.getComponent().getMeasures();
				for (Measures measure : measures) {
					if(measure.getMetric().equals("branch_coverage")){
						msg.append(" 覆盖率:"+measure.getValue()+"% ");
					}
				}
				for (Measures measure : measures) {
					if(measure.getMetric().equals("uncovered_conditions")){
						msg.append("未覆盖分支:"+measure.getValue());
					}
				}
			}
			serverThread.messages.addElement(new String(msg));
		}
	}

	/**
	 * 登录GitLab
	 ******************************************
	 * @author HuangFeng [2017年7月5日 下午1:01:10]
	 * @version 1.0
	 ******************************************
	 */
	private void loginGitLab() {
		String result = build("gitLab","https://git.cae.com/users/sign_in");
		int index = result.indexOf("<input type=\"hidden\" name=\"authenticity_token\" value=\"");
		String authenticity_token = result.substring(index + 54, index + 142);
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("utf8", "&#x2713;");
		param.put("authenticity_token", authenticity_token);
		param.put("user[login]", git_username);
		param.put("user[password]", git_password);
		param.put("user[remember_me]", "0");
		doPost("gitLab","https://git.cae.com/users/sign_in", param);
	}

	/**
	 * 创建HttpClient对象，信任所有签名
	 ******************************************
	 * @author HuangFeng [2017年7月5日 下午1:02:10]
	 * @version 1.0
	 ******************************************
	 * @return HttpClient对象
	 */
	private CloseableHttpClient createSSLClientDefault() {
		SSLContext sslContext;
		try {
			sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
				// 信任所有
				public boolean isTrusted(X509Certificate[] xcs, String string) {
					return true;
				}
			}).build();
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);
			return HttpClients.custom().setSSLSocketFactory(sslsf).build();
		} catch (KeyStoreException ex) {
			ex.printStackTrace();
		} catch (NoSuchAlgorithmException ex) {
			ex.printStackTrace();
		} catch (KeyManagementException ex) {
			ex.printStackTrace();
		}
		return HttpClients.createDefault();
	}

	/**
	 * 构建httpclient
	 ******************************************
	 * @author HuangFeng [2017年7月5日 下午1:10:02]
	 * @version 1.0
	 ******************************************
	 * @param name 名称
	 * @param url 链接
	 * @return 对象
	 */
	private String build( String name , String url) {
		CloseableHttpClient httpClient = createSSLClientDefault();
		HttpGet get = new HttpGet(url);
		CloseableHttpResponse response = null;
		String result = "";
		try {
			response = httpClient.execute(get);
			HttpEntity entity = response.getEntity();
			result = EntityUtils.toString(entity, "UTF-8");
			httpclientMap.put(name, httpClient);
		} catch (IOException ex) {
			ex.printStackTrace();
		} finally {
			if (null != response) {
				try {
					EntityUtils.consume(response.getEntity());
				} catch (IOException ex) {
					ex.printStackTrace();
				}
			}
		}
		return result;
	}

	/**
	 * Post请求
	 ******************************************
	 * @author HuangFeng [2017年7月5日 下午1:10:47]
	 * @version 1.0
	 ******************************************
	 * @param name HttpClient对象名
	 * @param url 链接
	 * @param params 请求参数
	 * @return 结果
	 */
	private String doPost(String name ,  String url, Map<String, Object> params) {
		HttpPost post = new HttpPost(url);
		CloseableHttpResponse response = null;
		if (null != params && !params.isEmpty()) {
			List<NameValuePair> nvpList = new ArrayList<NameValuePair>();
			for (Map.Entry<String, Object> entry : params.entrySet()) {
				NameValuePair nvp = new BasicNameValuePair(entry.getKey(), entry.getValue().toString());
				nvpList.add(nvp);
			}
			post.setEntity(new UrlEncodedFormEntity(nvpList, Charset.forName("UTF-8")));
		}
		String result = "";
		try {
			response = httpclientMap.get(name).execute(post);
			HttpEntity entity = response.getEntity();
			result = EntityUtils.toString(entity, "UTF-8");
		} catch (IOException ex) {
			ex.printStackTrace();
		} finally {
			if (null != response) {
				try {
					EntityUtils.consume(response.getEntity());
				} catch (IOException ex) {
					ex.printStackTrace();
				}
			}
		}
		return result;
	}
	
	/**
	 * Get请求
	 ******************************************
	 * @author HuangFeng [2017年7月5日 下午1:10:47]
	 * @version 1.0
	 ******************************************
	 * @param name HttpClient对象名
	 * @param url 链接
	 * @param params 请求参数
	 * @return 结果
	 */
	private String doGet(String name , String url, Map<String, Object> params) {
		StringBuilder sb = new StringBuilder("");
		if (null != params && !params.isEmpty()) {
			int i = 0;
			for (String key : params.keySet()) {
				if (i == 0) {
					sb.append("?");
				} else {
					sb.append("&");
				}
				sb.append(key).append("=").append(params.get(key));
				i++;
			}
		}
		CloseableHttpResponse response = null;
		HttpGet get = new HttpGet(url + sb.toString());
		String result = "";
		try {
			response = httpclientMap.get(name).execute(get);
			if (response.getStatusLine().getStatusCode() == 200) {
				HttpEntity entity = response.getEntity();
				if (null != entity) {
					result = EntityUtils.toString(entity, "UTF-8");
				}
			}
		} catch (IOException ex) {
			ex.printStackTrace();
		} finally {
			if (null != response) {
				try {
					EntityUtils.consume(response.getEntity());
				} catch (IOException ex) {
					ex.printStackTrace();
				}
			}
		}
		return result;
	}

	public void setFlag_exit(boolean b) {
		flag_exit = b;
	}

}
